package istar.behaviour;

import java.util.Iterator;
import java.util.List;

import istar.IElement;
import istar.IistarBehaviour;
import istar.agent.IstarJadeAgent;
import istar.impl.AbstractElement;
import istar.impl.AbstractMainGoal;
import istar.impl.MeansEndLink;
import istar.impl.Task;
import istar.impl.TaskDecompositionLink;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public abstract class AbstractIstarBehaviour extends Behaviour implements IistarBehaviour{

	private IElement element;
	private boolean error = false;
	private int estimatedTime = 1;
	

	//public static int COMMITED = 103;
	
	public abstract void myAction() throws Exception;
	
	public abstract int myOnEnd();
	
	

	@Override
	public long getEstimatedWaitingTime() {
		return estimatedTime;
	}

	public void setEstimatedTime(int estimatedTime) {
		this.estimatedTime = estimatedTime;
	}

	public AbstractIstarBehaviour (IElement _element){
		super();
		this.element = _element;
		this.setBehaviourName(_element.getName());
	}

	public AbstractIstarBehaviour (IstarJadeAgent _agent, IElement _element){
		super(_agent);
		this.element = _element;
		this.setBehaviourName(_element.getName());
	}
	
	@Override
	public void action() {

		String ticket = ((IstarJadeAgent)myAgent).getTicket();

		// checking existence of proposal messages
		ACLMessage msgReply = null;
		MessageTemplate mtPropose = MessageTemplate.MatchPerformative(ACLMessage.PROPOSE);
		ACLMessage msgPropose = myAgent.receive(mtPropose);
		if (msgPropose!=null){
			msgReply = msgPropose.createReply();
			ACLMessage waitMsg = ((IstarJadeAgent)myAgent).getWaitingMessages().get(ticket);
			if (waitMsg!=null){
				msgReply.setPerformative(ACLMessage.REJECT_PROPOSAL);
			}
			else {
				msgReply.setPerformative(IistarBehaviour.BUSY);
				msgReply.setContent("<EstimatedTime="+ ((AbstractMainGoal)element.getMain()).getEstimatedTotalTime()+ "/>");
			}
			myAgent.send(msgReply);
		}
		
		// checking existence of waiting messages
		MessageTemplate mtWaiting = MessageTemplate.MatchPerformative(ACLMessage.PROPOSE);
		ACLMessage msgWaiting = myAgent.receive(mtWaiting);
		if (msgWaiting!=null){
			((IstarJadeAgent)myAgent).getWaitingMessages().put(ticket, msgWaiting);
		}

		try {
			//changed here
			if (!element.isMain()){
				if (((IstarJadeAgent)myAgent).getParameter(getExecutionNumber(), element.getName())==null){
					Object mainParameter = ((IstarJadeAgent)myAgent).getParameter(getExecutionNumber(), element.getMain().getName());
					((IstarJadeAgent)myAgent).setParameter(getExecutionNumber(), element.getName(), mainParameter);
				}
					
			}

			myAction();
		} catch (Exception e) {
			e.printStackTrace();
			error = true;
			this.element.getMain().getContent().clear();
			this.element.getMain().getContent().add(e.getMessage());
		}
	}
	



	@Override
	public int onEnd() {
		if (error){
			((IstarJadeAgent)myAgent).log("Ending " + this.getBehaviourName() + " with error");
			//System.out.println("Ending " + this.getBehaviourName() + " with error");
			return ERROR_STATE_CODE;
		}
		else
			return myOnEnd();
	}

	public void log(String _phrase){
			((IstarJadeAgent)myAgent).log( _phrase);
	}
	
	public IElement getElement() {
		return element;
	}

	public void setElement(IElement element) {
		this.element = element;
	}

	@Override
	public String getExecutionNumber() {
		return this.element.getExecutionNumber();
	}
	
	public List<Object> getParameters(){
		if (!element.getSupports().isEmpty())
			return element.getSupports().get(0).getOwner().getContent();
		
		return null;
	}

	/*
	public void setResult(List<Object> _content){
		
		if (!_content.isEmpty()){
			getElement().getContent().clear();
			getElement().getContent().addAll(_content);
			//((IstarJadeAgent)myAgent).setKnowledgeElement(getElement().getExecutionNumber(), getElement());
			((IstarJadeAgent)myAgent).setKnowledgeObject(getElement().getExecutionNumber(), getElement().getName(), getElement());
			log("Setting knowledge element " + _content.toString());
			
			Iterator<TaskDecompositionLink> itSupps =  getElement().getSupports().iterator();
			while (itSupps.hasNext()){
				IElement superTask = itSupps.next().getOwner();
				superTask.getContent().clear();
				superTask.getContent().addAll(_content);
				((IstarJadeAgent)myAgent).setKnowledgeElement(getElement().getExecutionNumber(), superTask);
			}
			
			if (getElement().getClass().equals(Task.class)){
				Iterator<MeansEndLink> itMeansFor =  ((Task)getElement()).getMeansFor().iterator();
				while (itMeansFor.hasNext()){
					IElement end = itMeansFor.next().getOwner();
					end.getContent().clear();
					end.getContent().addAll(_content);
					((IstarJadeAgent)myAgent).setKnowledgeElement(getElement().getExecutionNumber(), end);
				}
			}
			
		}
		
	}
	*/
}
